package nl.Viewer;

import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import nl.Viewer.Sessions.SessionManager;
import nl.Viewer.ViewManager.ViewManager;

/**
 * The main class for the Client application. On startup, the ViewManager is instantiated, and the login dialog and the
 * dataset selection dialog is shown.
 * 
 * @author Jeroen Verschuur
 * 
 */

public class Application implements WindowListener {
   public final static String   applicationName = "Viewer 1.0";
   private static Application   instance;
   public static JFrame         frame;
   public static GUI            gui;
   public static SessionManager sessionManager;
   public static ViewManager    viewManager;
   public static String         serverAddress   = "10.0.4.170:8080/ViewerServer/services/Viewer";

   /**
    * @param args
    */
   public static void main( String[] args ) {
      try {
         UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
         System.out.println( "System Look-And-Feel: " + UIManager.getSystemLookAndFeelClassName() );
      }
      catch( Exception e ) {
         e.printStackTrace();
      }

      // parse the command line parameters
      for( String argument : args ) {
         // argument format should be --<argumentname>=<value>
         if( argument.startsWith( "--" ) && argument.length() > 4 ) {
            String[] split = argument.substring( 2 ).split( "=" );
            if( split.length == 2 ) {
               // --soapserver=<server address>
               if( split[0].equalsIgnoreCase( "soapserver" ) ) {
                  serverAddress = split[1];
               }
            }
         }
      }

      try {
         Application.getInstance();
      }
      catch( Exception e ) {
         e.printStackTrace();
      }
   }

   /**
    * Get the instance of this singleton class. This method can be accessed by any other class in any other package.
    * 
    * @return this instance
    * @throws Exception
    */
   public synchronized static Application getInstance() {
      if( instance == null ) {
         synchronized( Application.class ) {
            instance = new Application();
         }
      }
      return instance;
   }

   /**
    * Constructor of the singleton class. This is a private constuctor, so only this class can construct itself once.
    * 
    * @throws Exception
    */
   private Application() {
      /**
       * initialize
       */
      viewManager = ViewManager.getInstance();

      sessionManager = new SessionManager();

      // setup the GUI and wait until the frame is ready
      try {
         SwingUtilities.invokeAndWait( new Runnable() {
            public void run() {
               createAndShowGUI();
            }
         } );
      }
      catch( Exception ie ) {
         // ignore
      }
      // start all other tasks (login, dataset selection, etc.)
      try {
         SwingUtilities.invokeAndWait( new Runnable() {
            public void run() {
               gui.doLogin();
            }
         } );
      }
      catch( Exception ie ) {
         // ignore
      }
   }

   /**
    * createAndShowGUI will create the application frame, and set-up a new GUI object which is responsible for laying
    * out the rest of the user interface
    * 
    */
   private void createAndShowGUI() {
      // Create the frame.
      frame = new JFrame( applicationName );
      frame.setSize( (int)( 1024 ), (int)( 768 ) );
      frame.setLocationRelativeTo( null );

      // Create the gui and add it to the content pane of the frame.
      gui = new GUI();
      sessionManager.addConnectionStateListeners( gui );

      // add the menu bar
      frame.setJMenuBar( gui.createMenuBar() );
      frame.getContentPane().add( gui );

      // Set the frame properties and show it.
      frame.addWindowListener( this );

      frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      frame.setVisible( true );
   }

   /**
    * This method is called whenever the application window will be closed (for example by pressing the close-icon on
    * the application frame)
    * 
    */
   public void windowClosing( WindowEvent arg0 ) {
      // TODO: show progress?

      if( sessionManager != null )
         sessionManager.shutdown();

      if( gui != null )
         gui.shutdown();

   }

   /**
    * This will forcefully close the application
    * 
    */

   public static void shutdown() {
      // this will call windowClosing, which will start the shutdown
      System.exit( 0 );
   }

   /**
    * Convenience method for showing application-wide error messages as a message dialog
    * 
    * @param title
    * @param message
    */
   public static void showErrorMessage( String title, String message ) {
      JOptionPane.showMessageDialog( frame, message, title, JOptionPane.ERROR_MESSAGE );
      System.err.println( message );

   }

   /* Unused callbacks below */

   public void windowActivated( WindowEvent arg0 ) {
   }

   public void windowClosed( WindowEvent arg0 ) {
   }

   public void windowDeactivated( WindowEvent arg0 ) {
   }

   public void windowDeiconified( WindowEvent arg0 ) {
   }

   public void windowIconified( WindowEvent arg0 ) {
   }

   public void windowOpened( WindowEvent arg0 ) {
   }

}
